/*
 * =====================================================================================
 *
 *       Filename:  dispatcherLocal.cpp
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  08/01/2012 08:41:27 PM
 *       Revision:  none
 *       Compiler:  gcc/g++
 *
 *         Author:  wangtengchao , wangtengchao AT gmail.com
 *   Organization:  
 *
 * =====================================================================================
 */


#include "dispatcher.h"
#include "epoll.h"
#include "poll.h"
#include "acceptor.h"
#include "eventHandler.h"
#include "netHelp.h"
#include<cstdio>


using namespace inm::net;

Dispatcher::Dispatcher()
{
#ifdef linux
   demultiplexer_ = new Epoll;//for linux
#else
    demultiplexer_ = new Poll;//for solaris and other paltform 
#endif
    demultiplexer_->setDispatcher(this);
}

Dispatcher::~Dispatcher()
{
    //
	if(!demultiplexer_->isRunning())
    	delete demultiplexer_;
    //delete map content
}

void Dispatcher::quit()
{
   demultiplexer_->quit();
}

void Dispatcher::registerHandler(const EventHandlerPtr &eh, const short &et)
{
    int fd = eh->getSocketFdHandle();
    idEventhandlerMap_.insert(std::make_pair(fd,eh));//add to eventhandler map
    demultiplexer_->registerEvent(fd,et);//pass the fd to demultiplexer
    eh->setCurrentEventTypes(et);//set for updateEventHandler

}

void Dispatcher::updateHandler(const EventHandlerPtr &eh, const short &updateType, const short &et)
{//modify
    short newEventTypes = eh->getCurrentEventTypes();
    if(updateType == EVENT_ADD)
        newEventTypes = eh->getCurrentEventTypes() | et;//add to previous types
    else
        if(updateType == EVENT_DEL)
        {
            newEventTypes = eh->getCurrentEventTypes() & ~et;//delete from previous types
            if(newEventTypes == 0)//when delete all
                removeHandler(eh,0);
        }
    demultiplexer_->updateEvent(eh->getSocketFdHandle(),et);
}

void Dispatcher::removeHandler(const EventHandlerPtr &eh, const short &et)
{//will delete eventhandler and all event in dimultiplexer
    int fd = eh->getSocketFdHandle();
    demultiplexer_->removeEvent(fd,et);//in epoll et doesn't be used
    idEventhandlerMap_.erase(idEventhandlerMap_.find(fd));//delete from eventhandler map

}
void Dispatcher::handleEvents()
{
    demultiplexer_->handleEvents();
}
const EventHandlerPtr& Dispatcher::getEventHandlerByFd(int fd) const
{
    return  (idEventhandlerMap_.find(fd))->second;
}
void Dispatcher::doTasks()
{//need mutex because other thread may add fucntor into afterTasks
    std::vector<Functor> functors;
    {
        inm::concurrency::MutexLockGuard lock(taskMutex_);
        functors.swap(tasks_);
    }
    size_t num = functors.size();
    for(size_t i = 0;i<num;i++)
        functors[i]();
}
void Dispatcher::addToTasks(const Functor &f)
{
    inm::concurrency::MutexLockGuard guard(taskMutex_);
    tasks_.push_back(f);
    //printf("addtotasks\n");
}


